package com.zz.common.utils;

import com.zz.common.config.Constants;
import com.zz.common.enums.AttrKey;
import com.zz.common.exception.TunnelException;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

@Slf4j
@SuppressWarnings("all")
public class ObjectUtil {


    /**
     * 空值判断
     * @param object
     * @return
     */
    public static boolean isEmpty(Object object) {
        if (null == object) {
            return true;
        }
        if (object instanceof List) {
            return ((List) object).isEmpty();
        }
        if (object instanceof String) {
            return Constants.Strings.EMPTY_STR.equals((String) object);
        }
        if (object instanceof byte[]) {
            return ((byte[]) object).length < 1;
        }
        if (object instanceof Map) {
            return ((Map) object).isEmpty();
        }
        if (object instanceof Channel) {
            return false;
        }
        return false;
    }

    /**
     * 是否不为空
     * @param object
     * @return
     */
    public static boolean isNotEmpty(Object object) {
        return !isEmpty(object);
    }

    /**
     * 是否都不为空
     * @param objs
     * @return
     */
    public static boolean isNotEmptys(Object... objs) {
        for (Object obj : objs) {
            if (isEmpty(obj)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 是否都为空
     * @param objs
     * @return
     */
    public static boolean isEmptys(Object... objs) {
        for (Object obj : objs) {
            if (isEmpty(obj)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否不为NULL
     * @param obj
     * @return
     */
    public static boolean isNotNull(Object obj) {
        return obj != null;
    }

    public static boolean isNull(Object obj) {
        return obj == null;
    }

    /**
     * ByteBuf转byte[]
     * @param buf
     * @return
     */
    public static byte[] byteProcess(ByteBuf buf) {
        byte[] bytes = new byte[buf.readableBytes()];
        buf.readBytes(bytes);
        buf.release();
        return bytes;
    }

    /* -------------------------------------------------------------------- */
    /**
     * 设置通道读写状态
     * @param channel
     */
    public static void setReadable(Channel channel) {
        if (isNotNull(channel)) {
            channel.config().setAutoRead(true);
        }
    }

    public static void setNotReadable(Channel channel) {
        if (isNotNull(channel)) {
            channel.config().setAutoRead(true);
        }
    }

    public static void setReadable(ChannelHandlerContext context) {
        if (isNotNull(context)) {
            context.channel().config().setAutoRead(true);
        }
    }

    public static void setNotReadable(ChannelHandlerContext context) {
        if (isNotNull(context)) {
            context.channel().config().setAutoRead(true);
        }
    }

    public static void setReadable(Channel channel, boolean readable) {
        if (isNotNull(channel)) {
            channel.config().setAutoRead(readable);
        }
    }

    public static void closeChannel(Channel channel, String isFair) {
        if (isNotNull(channel) && Constants.Strings.FAIL.equals(isFair)) {
            channel.close();
        }
    }

    public static void closeChannel(Channel channel) {
        closeChannel(channel, Constants.Strings.FAIL);
    }

    public static void closeContext(ChannelHandlerContext context, String isFair) {
        closeChannel(context.channel(), isFair);
    }


    public static void setFieldNull(Channel context, AttributeKey... attributeKey) {
        if (isNotNull(context)) {
            for (AttributeKey key : attributeKey) {
                context.attr(key).set(null);
            }
        }
    }

    public static void setFieldNull(ChannelHandlerContext context, AttributeKey... attributeKeys) {
        if (isNotNull(context)) {
            Channel channel = context.channel();
            setFieldNull(channel, attributeKeys);
        }
    }

    /* -------------------------------------------------------------------- */

    /**
     * Map 构造器
     */
    public static class NewMap {

        private Map<AttrKey, Object> objectMapp;
        public NewMap() {}

        public static NewMap builder() {
            NewMap newMap = new NewMap();
            newMap.objectMapp = new HashMap<>();
            return newMap;
        }

        public NewMap put(AttrKey key, Object value) {
            objectMapp.put(key, value);
            return this;
        }

        public Map<AttrKey, Object> build() {
            return objectMapp;
        }

    }

    public static <T> T getMapValue(Map<AttrKey, Object> map, AttrKey key, T defaultValue) {
        return Optional.ofNullable(map.get(key)).map(o -> (T) o).orElse(defaultValue);
    }

    public static Object getMapValue(Map<AttrKey, Object> map, AttrKey key) {
        return Optional.ofNullable(map.get(key)).orElse(null);
    }


    public static <T> T getMapValue(Map map, String key, T defaultValue) {
        return Optional.ofNullable(map.get(key)).map(o -> (T) o).orElse(defaultValue);
    }

    public static Object getMapValue(Map map, String key) {
        return Optional.ofNullable(map.get(key)).orElse(null);
    }

    public static <T> T getMapValue(Map map, String key, Class<T> clazz, T defaultValue) {
        return Optional.ofNullable(map.get(key)).map(o -> (T) o).orElse(defaultValue);
    }

    public static Integer toInt(String num) {
        if (isEmpty(num)) {
            log.error("num is empty");
            return 0;
        }
        return Integer.parseInt(num);
    }


}
